package com.daydayup.learn;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 线程池的优雅关闭
 */
public class ThreadPoolGracefulShutdownDemo {
    public static void main(String[] args) {
        //shutdownTest();
        //shutdownNowTest();
        //shutdownAwaitTerminationTest();
        //shutdownNowAwaitTerminationTest();
        finalShutdownTest();
    }

    static void finalShutdownTest()
    {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 10; i++) {
            System.out.println("第:"+i+"次提交");
            threadPool.execute(new Task(i));
            if (i == 5){
                finalOKShutdownNowAwaitTermination(threadPool);
            }
        }
    }

    /**
     * 官方推荐的优雅关停
     * @param threadPool
     */
    static void finalOKShutdownNowAwaitTermination(ExecutorService threadPool){
        if (threadPool != null && !threadPool.isShutdown()) {
            threadPool.shutdown();
            try{
                if (!threadPool.awaitTermination(120, TimeUnit.SECONDS)) {
                    threadPool.shutdownNow();
                    if (!threadPool.awaitTermination(120, TimeUnit.SECONDS)) {
                        System.out.println("Pool did not terminate");
                    }
                }
            } catch (InterruptedException e){
                threadPool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    static void shutdownNowAwaitTerminationTest()
    {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 10; i++) {
            System.out.println("第:"+i+"次提交");
            try{
                threadPool.execute(new Task(i));
            }catch (RejectedExecutionException e){
                System.out.println("rejected,task-"+i);
            }

            if (i == 5){
                // 不会再接受新任务的提交
                // 在shutdown调用之前的任务会被执行下去,待执行的任务和正在执行的任务都不会取消,将继续执行
                // 如果已经shutdown了,再调用不会有其他影响
                List<Runnable> runnables = threadPool.shutdownNow();
                System.out.println("还有"+runnables.size()+"任务未被执行.");
            }
        }
        try{
            // 仅等待2秒钟,如果在2秒内没有执行完,不等了,执行下面的逻辑,线程池中的还未执行完的任务继续执行
            boolean isStop = threadPool.awaitTermination(2, TimeUnit.SECONDS);
            System.out.println("is pool isStop:"+isStop);
            System.out.println(Thread.currentThread().getName()+"\t 222222222222222");
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName()+",收到了中断异常......");
            e.printStackTrace();
        }

        System.out.println("-------------------");
        System.out.println(Thread.currentThread().getName()+"\t mission is over");
        System.out.println();
    }

    /**
     * 第6个任务开始及之后的任务都被拒绝了,1-5号任务正常执行
     * 所以shutdown方法将线程池状态置为SHUTDOWN，线程池并不会立即停止
     * 要等正在执行和队列里等待的任务执行完才会停止
     */
    static void shutdownAwaitTerminationTest()
    {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 10; i++) {
            System.out.println("第:"+i+"次提交");
            try{
                threadPool.execute(new Task(i));
            }catch (RejectedExecutionException e){
                System.out.println("rejected,task-"+i);
            }

            if (i == 5){
                // 不会再接受新任务的提交
                // 在shutdown调用之前的任务会被执行下去,待执行的任务和正在执行的任务都不会取消,将继续执行
                // 如果已经shutdown了,再调用不会有其他影响
                threadPool.shutdown();
            }
        }
        try{
            // 仅等待2秒钟,如果在2秒内没有执行完,不等了,执行下面的逻辑,线程池中的还未执行完的任务继续执行
            boolean isStop = threadPool.awaitTermination(2, TimeUnit.SECONDS);
            System.out.println("is pool isStop:"+isStop);
            System.out.println(Thread.currentThread().getName()+"\t 111111111111111");
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName()+",收到了中断异常......");
            e.printStackTrace();
        }

        System.out.println("-------------------");
        System.out.println(Thread.currentThread().getName()+"\t mission is over");
        System.out.println();
    }

    /**
     * 不会再接受新任务的提交
     * 尝试停止所有正在执行的任务
     * 待执行的任务会取消并返回等待任务的列表
     * shutdownNow返回时,这些等待的任务将从队列中清空
     * 尝试取消执行中的任务,仅仅只是尝试,成功与否取决于是否响应InterruptedException,以及对其做出的反应
     * 所以shutdownNow方法将线程池状态置为STOP,试图让线程池立即停止,但不能保证一定立即停止,要等所有正在执行的任务执行完才能停止
     */
    static void shutdownNowTest()
    {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 10; i++) {
            System.out.println("第:"+i+"次提交");
            try{
                threadPool.execute(new Task(i));
            } catch (RejectedExecutionException e){
                System.out.println("rejected,task-"+i);
            }

            if (i == 5){
                List<Runnable> runnables = threadPool.shutdownNow();
                if (!runnables.isEmpty()){
                    System.out.println("还有"+runnables.size()+"个任务还未执行完成就被终止了");
                }
            }
        }
    }

    /**
     * 第6个任务开始及之后的任务都被拒绝了,1-5号任务正常执行
     * 所以shutdown方法将线程池状态置为SHUTDOWN，线程池并不会立即停止
     * 要等正在执行和队列里等待的任务执行完才会停止
     */
    static void shutdownTest()
    {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 10; i++) {
            System.out.println("第:"+i+"次提交");
            threadPool.execute(new Task(i));
            if (i == 5){
                // 不会再接受新任务的提交
                // 在shutdown调用之前的任务会被执行下去,待执行的任务和正在执行的任务都不会取消,将继续执行
                // 如果已经shutdown了,再调用不会有其他影响
                threadPool.shutdown();
            }
        }
    }

    private static class Task implements Runnable {
        private int i;

        public Task(int i) {
            this.i = i;
        }
        @Override
        public void run()
        {
            try {
                System.out.println(Thread.currentThread().getName()+",当前的i值为"+this.i);
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+",我收到了中断异常");
                e.printStackTrace();
            }
        }
    }
}
